package ElevatorPackage;

/**
 * Created by Connor Madden.
 * User: Connor Madden
 * Date: 17/08/11
 * Time: 3:26 PM
 */
public class StepMove extends Thread {
    Elevator elevator;

    public StepMove(Elevator elevator) {
        this.elevator = elevator;
    }

    public void run() {
        while (true) {
            /*
           If has no destination, get new destination.
           If cannot get destination set status to waiting and return
            */
            if (!elevator.isHasDestination()) {
                int d = elevator.getNextDestination();
                if (d != -1) {  // if can get next destination
                    elevator.setDestination(d);
                    elevator.setHasDestination(true);
                    elevator.setChangeAndNotifyObservers(Elevator.ElevatorAction.GET_DESTINATION);
                } else {
                    elevator.setStatus(Elevator.Status.WAITING);
                    elevator.setChangeAndNotifyObservers(Elevator.ElevatorAction.WAITING);
                    return;
                }
            }
            /*
           If not at location, move. Then arrive
            */
            if (elevator.getDestination() == elevator.getLocation()) {
                elevator.setPrevLocation(elevator.getLocation());
                arrive();
            } else {   // move
                elevator.setStatus(Elevator.Status.MOVE);
                while (elevator.getDestination() != elevator.getLocation()) {
                    elevator.setChangeAndNotifyObservers(Elevator.ElevatorAction.MOVE);
                    try {
                        Thread.sleep(elevator.getStepTime());                 // do nothing for stepTime milliseconds
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    elevator.setPrevLocation(elevator.getLocation());
                    if (elevator.getDestination() > elevator.getLocation())
                        elevator.setLocation(elevator.getLocation() + 1);
                    else if (elevator.getDestination() < elevator.getLocation())
                        elevator.setLocation(elevator.getLocation() - 1);
                    elevator.setChangeAndNotifyObservers(Elevator.ElevatorAction.ARRIVE_AT_FLOOR);
                    arrive();
                }
            }
        }
    }

    private void arrive() {
        if (elevator.getLocation() == elevator.getDestination()) {
            elevator.setHasDestination(false);
            elevator.setChangeAndNotifyObservers(Elevator.ElevatorAction.ARRIVE_AT_DESTINATION);
        }
        if (elevator.hasDisembark(elevator.getLocation()) || elevator.hasActiveCall(elevator.getLocation(), elevator.getDirection()) || elevator.hasActiveCall(elevator.getLocation(), elevator.getDirection() * -1)) {
            elevator.setStatus(Elevator.Status.STOP);
            elevator.setChangeAndNotifyObservers(Elevator.ElevatorAction.STOP);
            elevator.setStatus(Elevator.Status.OPEN);
            elevator.setChangeAndNotifyObservers(Elevator.ElevatorAction.OPEN_DOOR);
            if (elevator.hasActiveCall(elevator.getLocation(), elevator.getDirection()) || elevator.hasActiveCall(elevator.getLocation(), elevator.getDirection() * -1)) {
                elevator.deactivateCall(elevator.getLocation());
            }
            if (elevator.hasDisembark(elevator.getLocation())) {
                elevator.removeDisembarkLocation(elevator.getLocation());
                elevator.setChangeAndNotifyObservers(Elevator.ElevatorAction.DISEMBARK_PASSENGERS);
            }
            try {
                Thread.sleep(elevator.getExchangeTime());            // do nothing for exchangeTime milliseconds
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            elevator.setStatus(Elevator.Status.STOP);
            elevator.setChangeAndNotifyObservers(Elevator.ElevatorAction.CLOSE_DOOR);
            elevator.setChangeAndNotifyObservers(Elevator.ElevatorAction.DEPART_FLOOR);
        }
    }
}


